package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"gitcode.com/deyiyangyang/bampoo/evl"
	"gitcode.com/deyiyangyang/bampoo/lex"
	"gitcode.com/deyiyangyang/bampoo/obj"
	"gitcode.com/deyiyangyang/bampoo/par"
	"gitcode.com/deyiyangyang/bampoo/rep"
)

func main() {
	// Create global environment
	env := obj.NewEnvironment()

	// Add boolean constants to global environment
	env.Set("#t", &obj.BooleanValue{Value: true})
	env.Set("#f", &obj.BooleanValue{Value: false})

	// Add builtin functions to environment
	builtins := evl.CreateBuiltinFunctions()
	for name, builtin := range builtins {
		env.Set(name, builtin)
	}

	// Create evaluator
	evaluator := evl.New(env)

	// Check if a script file is provided
	if len(os.Args) > 1 {
		// Run script file
		filename := os.Args[1]
		content, err := ioutil.ReadFile(filename)
		if err != nil {
			fmt.Printf("Error reading file %s: %s\n", filename, err)
			os.Exit(1)
		}

		// Lex, parse, and evaluate the script
		lexer := lex.New(string(content))
		parser := par.New(lexer)
		program := parser.ParseProgram()

		// Check for parser errors
		if len(parser.Errors()) > 0 {
			fmt.Println("Parser errors:")
			for _, err := range parser.Errors() {
				fmt.Printf("  %s\n", err)
			}
			os.Exit(1)
		}

		// Evaluate the program
		result, err := evaluator.Eval(program)
		if err != nil {
			fmt.Printf("Evaluation error: %s\n", err)
			os.Exit(1)
		}

		// Print the result of the last expression
		if result != nil {
			fmt.Println(result.String())
		}
	} else {
		// Start REPL
		fmt.Println("Bamboo Scheme Interpreter")
		fmt.Println("Type expressions and press Enter to evaluate.")
		fmt.Println("Type Ctrl+C to exit.")
		fmt.Println()

		repl := rep.New(evaluator)
		repl.Start(os.Stdin, os.Stdout)
	}
}
